import database, unittest, mox
import services.AuthenticationService as AuthenticationService

class AuthenticationTests(mox.MoxTestBase):

    def setUp(self):
        mox.MoxTestBase.setUp(self)
        self.session = self.mox.CreateMockAnything()
        self.mox.StubOutWithMock(database, "getSession")
        database.getSession().AndReturn(self.session)

    def test_getUser(self):
        import TestHelper
        self.session.begin(subtransactions=True).AndReturn(TestHelper.getTransactionMock(self.mox))

        query = self.mox.CreateMockAnything()
        self.session.query(database.User).AndReturn(query)

        query.filter(mox.Func(lambda clause: clause.right.value == "admin" and str(clause.left) == "users.login")).AndReturn(query)
        expected = self.mox.CreateMock(database.User)
        query.one().AndReturn(expected)

        self.mox.ReplayAll()

        actual = AuthenticationService.getUser("admin")
        self.assertEqual(expected, actual)

    def test_isAuthenticated(self):
        import TestHelper

        self.session.begin().AndReturn(TestHelper.getTransactionMock(self.mox))
        query = self.mox.CreateMockAnything()
        self.session.query(database.User).AndReturn(query)

        def _andPredicate(clause):
            return (str(clause.left) == "users.login" and clause.right.value == "login") or \
                   (str(clause.left) == "users.password" and clause.right.value == "password")

        query.filter(mox.Func(lambda v: len([clause for clause in v.clauses if _andPredicate(clause)]) == 2)).AndReturn(query)
        query.count().AndReturn(True)

        self.mox.ReplayAll()
        
        result = AuthenticationService.isAuthenticated("login", "password")
        self.assertTrue(result)